
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>精选工具推荐 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>精选工具推荐 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">一个完整的 `ThreadPoolExecutor` 构造函数包含哪七个核心参数？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">包含七个核心参数：1. `corePoolSize` (核心线程数)；2. `maximumPoolSize` (最大线程数)；3. `keepAliveTime` (空闲线程存活时间)；4. `unit` (存活时间的单位)；5. `workQueue` (工作队列)；6. `threadFactory` (线程工厂)；7. `handler` (拒绝策略)。</div>
          </div>
          <div class="card-source">来源: ThreadPoolExecutor 核心参数</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">当一个新任务提交到 `ThreadPoolExecutor` 时，它的完整处理流程是怎样的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">处理流程分为四步：1. 判断当前运行的线程数是否小于 `corePoolSize`，如果是，则创建新线程来执行任务。2. 如果线程数已达到 `corePoolSize`，则判断工作队列 `workQueue` 是否已满，如果未满，则将任务添加到队列中。3. 如果工作队列已满，则判断当前运行的线程数是否小于 `maximumPoolSize`，如果未满，则创建新的非核心线程来执行任务。4. 如果线程数也达到了 `maximumPoolSize`，则执行拒绝策略 `handler`。</div>
          </div>
          <div class="card-source">来源: 线程池执行流程</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">请列举并简述 `ThreadPoolExecutor` 内置的四种拒绝策略。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">1. `AbortPolicy` (默认策略): 直接抛出 `RejectedExecutionException` 异常，阻止系统正常运行。2. `CallerRunsPolicy`: 将任务回退到调用者，由提交任务的线程来执行该任务。3. `DiscardOldestPolicy`: 丢弃队列中最旧的一个任务，然后尝试重新提交当前任务。4. `DiscardPolicy`: 直接丢弃当前任务，不做任何处理。</div>
          </div>
          <div class="card-source">来源: 线程池拒绝策略</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">在配置线程池时，如何根据任务是CPU密集型还是IO密集型来设定合理的线程数？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">对于CPU密集型任务（如计算、加密），应将线程数配置为 `N_cpu + 1`，以减少上下文切换的开销。对于IO密集型任务（如数据库读写、网络请求），由于线程会因等待IO而阻塞，应配置更多的线程，通常为 `2 * N_cpu`，以充分利用CPU资源。</div>
          </div>
          <div class="card-source">来源: 如何合理配置线程池</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">Java内存模型（JMM）被设计出来的根本目的是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">JMM的根本目的是为了屏蔽各种硬件和操作系统的内存访问差异，使得Java程序在不同平台下都能达到一致的内存访问效果。它主要致力于解决多线程环境下由于缓存、指令重排等问题引发的原子性、可见性和有序性问题。</div>
          </div>
          <div class="card-source">来源: Java 内存模型 (JMM)</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">请分别解释Java内存模型（JMM）的三大特性：原子性、可见性和有序性。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">1. 原子性 (Atomicity)：指一个或多个操作作为一个不可分割的单元，要么全部执行成功，要么全部不执行。2. 可见性 (Visibility)：指当一个线程修改了共享变量的值，其他线程能够立即得知这个修改。3. 有序性 (Ordering)：指程序执行的顺序与代码中定义的顺序一致，但编译器和处理器为了优化可能会进行指令重排序。</div>
          </div>
          <div class="card-source">来源: JMM 的三大特性</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">`volatile` 关键字是如何在JMM中保证可见性和有序性的？它能保证原子性吗？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`volatile` 关键字通过两个机制起作用：1. 保证可见性：当一个线程修改了被`volatile`修饰的变量，新值会立即同步到主内存，并使其他线程的本地缓存失效。2. 保证有序性：通过插入内存屏障来禁止指令重排序，确保其前后的指令按代码顺序执行。但是，`volatile` 关键字不保证操作的原子性。</div>
          </div>
          <div class="card-source">来源: volatile 关键字</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">`synchronized` 关键字是如何同时保证JMM的原子性、可见性和有序性这三大特性的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`synchronized` 通过以下方式保证三大特性：1. 原子性：通过 `monitorenter` 和 `monitorexit` 字节码指令，确保被它修饰的代码块在同一时间只有一个线程能执行。2. 可见性：在对变量解锁（unlock）前，JMM规定必须将此变量同步回主内存。3. 有序性：由于同一时间只有一个线程能获取锁，代码块内的操作是串行执行的，从而天然地保证了有序性。</div>
          </div>
          <div class="card-source">来源: synchronized 关键字</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">在并发编程中，JMM的“happens-before”原则扮演了什么核心角色？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">“happens-before”原则是JMM中判断数据是否存在竞争、线程是否安全的核心依据。它定义了在程序中两个操作之间的偏序关系，如果操作A `happens-before` 操作B，那么操作A的结果对操作B是可见的。这个原则旨在向程序员屏蔽底层复杂的重排序和内存可见性问题，提供一个更易于理解的跨线程内存可见性保证。</div>
          </div>
          <div class="card-source">来源: happens-before 原则</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
